package com.bjbn.util;

import cn.hutool.crypto.digest.DigestUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Random;

/**
 * Digest认证工具类
 */
@Slf4j
public class DigestAuthUtil {
    
    /**
     * 生成请求认证数据
     * @param wwwAuth 认证方式，来自头域：WWW-Authenticate，有：Digest Basic等
     * @param method 请求方法 POST GET等
     * @param uri uri
     * @param username 认证用户名
     * @param pwd 密码
     * @param times 次数
     * @return 生成后的认证密钥
     */
    public static String authorization(String wwwAuth, String method, String uri, String username, String pwd, int times) {
        String sResponse = "";
        String sRealm = "", sQop = "", sNonce = "", sOpaque = "";
        String sTimes = String.format("%08d", times); // 长度不足8位时前面补0
        String sCnonce = "";
        
        // 生成32位随机数
        Random r = new Random();
        r.setSeed(System.currentTimeMillis());
        String x = "d3f5a0f2d8e9a7b5f6e4f1c24e2c3f0d";
        for (int i = 0; i < 32; i++) {
            sCnonce += x.charAt(r.nextInt(x.length()));
        }

        int idx = wwwAuth.indexOf(" ");
        String challenge = "Digest";
        if (idx > 0) {
            challenge = wwwAuth.substring(0, idx);
        }
        
        if ("Digest".equalsIgnoreCase(challenge)) {
            // 摘要认证
            wwwAuth = wwwAuth.substring(idx).trim();
            String[] arrAuth = wwwAuth.split(",");
            for (String sVal : arrAuth) {
                if (sVal.split("=").length == 2) {
                    String key = sVal.split("=")[0].trim();
                    String value = sVal.split("=")[1].replaceAll("\"", "");
                    
                    if ("realm".equalsIgnoreCase(key)) {
                        sRealm = value;
                    } else if ("qop".equalsIgnoreCase(key)) {
                        sQop = value;
                    } else if ("nonce".equalsIgnoreCase(key)) {
                        sNonce = value;
                    } else if ("opaque".equalsIgnoreCase(key)) {
                        sOpaque = value;
                    } else if ("uri".equalsIgnoreCase(key)) {
                        uri = value;
                    }
                }
            }
            
            // MD5 md5=HA1:HD:HA2
            String sHa1 = "", sHd = "", sHa2 = "", sMd5 = "", sTemp = "";
            if (wwwAuth.toLowerCase().contains("algorithm=md5") || wwwAuth.toLowerCase().contains("algorithm=md5-sess")) {
                sTemp = username + ":" + sRealm + ":" + pwd + ":" + sNonce + ":" + sCnonce;
            } else {
                sTemp = username + ":" + sRealm + ":" + pwd;
            }
            sHa1 = DigestUtil.md5Hex(sTemp);
            
            sTemp = sNonce;
            if (isNotEmpty(sQop)) {
                sTemp = sNonce + ":" + sTimes + ":" + sCnonce + ":" + sQop;
            }
            sHd = sTemp;
            
            sTemp = method + ":" + uri;
            if ("auth-int".equals(sQop)) {
                sTemp += ":auth-int";
            }
            sHa2 = DigestUtil.md5Hex(sTemp);
            
            sTemp = sHa1 + ":" + sHd + ":" + sHa2;
            sMd5 = DigestUtil.md5Hex(sTemp);
            
            sResponse = "Digest username=\"" + username + "\",realm=\"" + sRealm + "\",";
            if (isNotEmpty(sQop)) {
                sResponse += "qop=" + sQop + ",nc=" + sTimes + ",";
            }
            sResponse += "nonce=\"" + sNonce + "\",uri=\"" + uri + "\",cnonce=\"" + sCnonce + "\",response=\"" + sMd5 + "\"";
            if (isNotEmpty(sQop)) {
                sResponse += ",opaque=\"" + sOpaque + "\"";
            }
        }
        
        return sResponse;
    }
    
    /**
     * 判断字符串是否不为空
     */
    private static boolean isNotEmpty(String str) {
        return str != null && !"".equals(str.trim());
    }
} 